import { Component, Label, director, Node, UITransform, tween, Animation, Sprite, Color, Vec2, Vec3, Camera, SpriteFrame, instantiate, RichText } from "cc";
import { ChannelBase } from "./ChannelBase";

export default abstract class ChannelTools extends Component {
    private backdrop: Node;

    private toast: Node;
    private toast_anim: Animation;
    private toast_content: Label;

    private dialog: Node;
    private dialog_title: Label;
    private dialog_content: Label;
    private dialog_sure: Node;
    private dialog_cancel: Node;
    private dialog_sure_label: Label;
    private dialog_cancel_label: Label;
    private dialog_ad_icon: Node;
    private dialog_sure_cb: Function;
    private dialog_cancel_cb: Function;

    private notice: Node;
    private last_notice: Node;

    private loading: Node;

    private toastList: Array<string>;

    protected channel: ChannelBase;

    onLoad() {
        this.initWindow();
        director.addPersistRootNode(this.node);
        this.backdrop = this.node.getChildByName("backdrop");
        this.toast = this.node.getChildByName("toast");
        this.toast_anim = this.toast.getComponent(Animation);
        this.toast_content = this.toast.getChildByName("content").getComponent(Label);

        this.Init();

        this.dialog = this.node.getChildByName("dialog");
        this.dialog_title = this.dialog.getChildByName("title").getComponent(Label);
        this.dialog_content = this.dialog.getChildByName("content").getComponent(Label);
        this.dialog_sure = this.dialog.getChildByName("btn_sure");
        this.dialog_cancel = this.dialog.getChildByName("btn_cancel");
        this.dialog_sure_label = this.dialog_sure.getChildByName("label").getComponent(Label);
        this.dialog_cancel_label = this.dialog_cancel.getChildByName("label").getComponent(Label);
        this.dialog_ad_icon = this.dialog_sure.getChildByName("ad_icon");
        this.dialog_sure.on(Node.EventType.TOUCH_END, this.onDialogSureClick, this);
        this.dialog_cancel.on(Node.EventType.TOUCH_END, this.onDialogCancelClick, this);

        this.toastList = new Array<string>();
        this.notice = this.node.getChildByName('notice');

        this.loading = this.node.getChildByName("loading");
    }

    private initWindow() {
        let windowSize = screen;
        this.node.getComponent(UITransform).width = windowSize.width;
        this.node.getComponent(UITransform).height = windowSize.height;
        this.node.setPosition(windowSize.width * 0.5, windowSize.height * 0.5);
    }

    protected abstract Init();

    /**
     * Toast提示
     * @param content 提示内容，单行显示，建议不要过长
     */
    public abstract ShowToast(content: string);
    /**
     * Toast提示(私有)
     * @param content 提示内容，单行显示，建议不要过长
     */
    protected showToast(content: string) {
        if (this.toast.active) {
            this.toastList.push(content);
        } else {
            this.toast_content.string = content;
            this.toast.active = true;
            this.scheduleOnce(() => { this.toast.getComponent(UITransform).width = this.toast_content.getComponent(UITransform).width + 42 });
            this.scheduleOnce(this.toastAnim, 1.2);
        }
    }
    /**
     * Toast动画
     */
    private toastAnim() {
        this.toast_anim.play();
        this.scheduleOnce(() => {
            this.hideToast();
        }, 0.32);
    }

    /**
     * 隐藏Toast提示
     */
    private hideToast() {
        this.unschedule(this.toastAnim);
        tween().target(this.toast).removeSelf();
        this.toast.active = false;
        this.toast.getComponent(Sprite).color = Color.WHITE;

        if (this.toastList.length > 0) {
            this.showToast(this.toastList.shift());
        }
    }

    /**
     * 显示提示框
     * @param data 提示框数据
     * @param ->title string 提框框标题(选填)，默认为“提 示”
     * @param ->content string 提框框标题(必填)，提示的内容
     * @param ->sure Function 点击确认的回调(选填)
     * @param ->cancel Function 点击取消的回调(选填)
     * @param ->sure_label 确认按键上的文字(选填)，默认为“确 定”
     * @param ->cancel_label string 取消按键上的文字(选填)，默认为“取 消”
     * @param ->ad_icon boolean 是否有广告图标(选填)，默认没有
     */
    public abstract ShowDialog(data: any);
    /**
     * 显示提示框(私有)
     * @param data 提示框数据
     * @param ->title string 提框框标题(选填)，默认为“提 示”
     * @param ->content string 提框框标题(必填)，提示的内容
     * @param ->sure Function 点击确认的回调(选填)
     * @param ->cancel Function 点击取消的回调(选填)
     * @param ->sure_label 确认按键上的文字(选填)，默认为“确 定”
     * @param ->cancel_label string 取消按键上的文字(选填)，默认为“取 消”
     * @param ->ad_icon boolean 是否有广告图标(选填)，默认没有
     */
    protected showDialog(data: any) {
        this.hideDialog();
        this.backdrop.active = true;
        //显示标题
        if (data.title) {
            this.dialog_title.string = data.title;
        } else {
            this.dialog_title.string = "提 示";
        }

        //显示内容
        if (data.content) {
            this.dialog_content.string = data.content;
        } else {
            this.dialog_content.string = "err";
        }

        //修改确定按键文字
        if (data.sure_label) {
            this.dialog_sure_label.string = data.sure_label;
        } else {
            this.dialog_sure_label.string = "确 定";
        }

        //修改取消按键文字
        if (data.cancel_label) {
            this.dialog_cancel_label.string = data.cancel_label;
        } else {
            this.dialog_cancel_label.string = "取 消";
        }

        /**
         * 显示广告图标
         */
        if (data.ad_icon) {
            this.dialog_sure_label.node.setPosition(28, this.dialog_sure_label.node.getPosition().y);
            this.dialog_ad_icon.active = true;
        } else {
            this.dialog_sure_label.node.setPosition(0, this.dialog_sure_label.node.getPosition().y);
            this.dialog_ad_icon.active = false;
        }

        if (!(data.sure || data.cancel)) {
            this.dialog_sure.setPosition(0, this.dialog_sure.getPosition().y);
            this.dialog_cancel.active = false;
        } else {
            this.dialog_sure.setPosition(-120, this.dialog_sure.getPosition().y);
            this.dialog_cancel.setPosition(120, this.dialog_cancel.getPosition().y);
            this.dialog_cancel.active = true;
        }

        this.dialog_sure_cb = data.sure;
        this.dialog_cancel_cb = data.cancel;
        this.dialog.active = true;

        tween(this.dialog).to(0.2, { scale: Vec3.ONE }).start();
    }

    private onDialogSureClick() {
        if (this.dialog_sure_cb) {
            this.dialog_sure_cb();
        }
        this.dialogMinAnim();
    }

    private onDialogCancelClick() {
        if (this.dialog_cancel_cb) {
            this.dialog_cancel_cb();
        }
        this.dialogMinAnim();
    }

    /**
     * 提示框缩小动画
     */
    private dialogMinAnim() {
        tween(this.dialog).sequence(tween(this.dialog).to(0.2, { scale: Vec3.ZERO }), tween(this.dialog).call(this.hideDialog.bind(this))).start();
    }

    /**
     * 隐藏提示框
     */
    private hideDialog() {
        this.unschedule(this.dialogMinAnim);
        tween().target(this.dialog).removeSelf();
        this.dialog.active = false;
        this.dialog.setScale(0, 0);
        if (!this.loading.active) this.backdrop.active = false;
    }

    /**
     * 显示加载界面
     */
    public ShowLoading() {
        this.loading.active = true;
        this.backdrop.active = true;
    }

    /**
     * 隐藏加载界面
     */
    public HideLoading() {
        this.loading.active = false;
        if (!this.dialog.active) this.backdrop.active = false;
    }

    protected onEnable(): void {
        this.node.setSiblingIndex(100);
    }

    /**显示通知 */
    public ShowNotice(content: string, icon?: SpriteFrame, color: Color = Color.WHITE) {
        let notice = instantiate(this.notice);
        notice.setParent(this.node);

        let label_node = notice.getChildByName('label');
        let label = label_node.getComponent(RichText);
        label.string = `<color=${color.toHEX()}>${content}</color>`;

        if (!!icon) {
            label_node.setPosition(20, 0);
            let sprite = label_node.getChildByName('icon');
            sprite.getComponent(Sprite).spriteFrame = icon;
            sprite.active = true;
        }

        let start = 0;
        if (!!this.last_notice) {
            start = this.last_notice.getPosition().y - 80;
            if (start > 0) start = 0
        }
        this.last_notice = notice;
        notice.setPosition(0, start);
        notice.setScale(0.8, 0.8);
        tween(notice).to(0.3, { scale: Vec3.ONE, position: new Vec3(0, start + 60) }).call(() => {
            tween(notice).to(1.5, { position: new Vec3(0, start + 360) }).call(() => {
                tween(notice).to(0.2, { position: new Vec3(0, start + 400), scale: Vec3.ZERO }).call(() => {
                    if (notice.uuid == this.last_notice.uuid) {
                        this.last_notice = null;
                    }
                    notice.destroy();
                }).start();
            }).start();
        }).start();
        notice.active = true;
    }

}
